package com.company.cloud.acct.modules.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.company.cloud.acct.constant.AcctCashConfig;
import com.company.cloud.acct.constant.AcctErrorEnum;
import com.company.cloud.acct.modules.api.constant.AcctOpTypeEnum;
import com.company.cloud.acct.modules.api.constant.AcctStateEnum;
import com.company.cloud.acct.modules.app.controller.req.AcctAccountInfoParam;
import com.company.cloud.acct.modules.app.controller.req.AcctCashApplyInfoParam;
import com.company.cloud.acct.modules.app.controller.req.AcctCashApplyParam;
import com.company.cloud.acct.modules.app.service.AcctCashService;
import com.company.cloud.acct.modules.app.utils.AcctIdUtils;
import com.company.cloud.acct.modules.base.entity.AccountCashInfo;
import com.company.cloud.acct.modules.base.entity.AccountDetailInfo;
import com.company.cloud.acct.modules.base.entity.AccountInfo;
import com.company.cloud.acct.modules.base.service.AccountCashInfoService;
import com.company.cloud.acct.modules.base.service.AccountDetailInfoService;
import com.company.cloud.acct.modules.base.service.AccountInfoService;
import com.company.cloud.acct.modules.cache.models.BankCardModel;
import com.company.cloud.acct.modules.cache.models.CashConfigModel;
import com.company.cloud.acct.modules.cache.service.AcctCacheService;
import com.company.cloud.common.bean.LoginSimpleUserInfo;
import com.company.cloud.common.constant.BaseConstant;
import com.company.cloud.common.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;

@Service
public class AcctCashServiceImpl implements AcctCashService {

    @Autowired
    private AccountInfoService accountInfoService;

    @Autowired
    private AcctCacheService acctCacheService;

    @Autowired
    private AccountCashInfoService accountCashInfoService;

    @Autowired
    private AccountDetailInfoService accountDetailInfoService;
    @Override
    public void apply(AcctCashApplyParam param, LoginSimpleUserInfo userInfo) {
        // 账户验证
        AccountInfo accountInfo = accountInfoService.getOne(new QueryWrapper<AccountInfo>()
                .eq("user_id", userInfo.getId())
                .eq("type", param.getAcctType())
        );
        if (accountInfo == null) {
            throw new BusinessException(AcctErrorEnum.NOT_ACCOUNT);
        }
        if (!accountInfo.getUserId().equals(userInfo.getId())) {
            throw new BusinessException(AcctErrorEnum.NOT_OWNER);
        }
        if (!AcctStateEnum.NORMAL.getCode().equals(accountInfo.getState())) {
            throw new BusinessException(AcctErrorEnum.Acct_state_error);
        }
        if (param.getFund().compareTo(accountInfo.getFund()) > 0) {
            throw new BusinessException(AcctErrorEnum.Acct_Insufficient);
        }
        // 银行卡验证
        Map<Integer, BankCardModel> bankCardMap = acctCacheService.getBankCardMapByUser(userInfo.getId());
        if (!bankCardMap.containsKey(param.getBankCardId())) {
            throw new BusinessException(AcctErrorEnum.NOT_OWNER);
        }
        // 获取公司提现配置信息
        CashConfigModel cashConfig = acctCacheService.getCompanyCashConfigCache(userInfo.getCompanyNo());
        if (null == cashConfig) {
            throw new BusinessException(AcctErrorEnum.Acct_config_null);
        }
        if (AcctCashConfig.CashFundType.ALL.equals(cashConfig.getCashFundType()) &&
                param.getFund().compareTo(accountInfo.getFund()) < 0) {
            throw new BusinessException(AcctErrorEnum.Acct_Cash_All);
        }
        BigDecimal fund = param.getFund(); // 提现金额
        BigDecimal taxFee = fund.multiply(cashConfig.getTaxCash()); // 税费
        BigDecimal serviceFee = BigDecimal.ZERO; // 手续费
        // 计算手续费
        if (BaseConstant.YNEnum.YES.getCode().equals(cashConfig.getIsFee())) { // 是否有手续费
            if (BaseConstant.YNEnum.YES.getCode().equals(cashConfig.getIsFree())) {
                Integer withdrawalTimes = 0;
                if (AcctCashConfig.FreeTimeIntervalType.MONTH.getCode().equals(cashConfig.getFreeTimeIntervalType())) {
                    QueryWrapper<AccountCashInfo> qw = new QueryWrapper<AccountCashInfo>()
                            .eq("user_id", userInfo.getId());
                    LocalDateTime now = LocalDateTime.now();
                    Integer year = now.getYear();
                    Integer month = now.getMonthValue();
                    qw.eq("DATE_FORMAT(cdt,'%Y-%m')", year + "-" + month);
                    withdrawalTimes = accountCashInfoService.count(qw);
                } else if (AcctCashConfig.FreeTimeIntervalType.YEAR.getCode().equals(cashConfig.getFreeTimeIntervalType())) {
                    QueryWrapper<AccountCashInfo> qw = new QueryWrapper<AccountCashInfo>()
                            .eq("user_id", userInfo.getId());
                    LocalDateTime now = LocalDateTime.now();
                    Integer year = now.getYear();
                    qw.eq("DATE_FORMAT(cdt,'%Y')", year);
                    withdrawalTimes = accountCashInfoService.count(qw);
                }
                if (withdrawalTimes > cashConfig.getFreeNum()) {
                    serviceFee = cashConfig.getFee();
                }
            } else {
                serviceFee = cashConfig.getFee();
            }
        }

        BigDecimal fundReal = fund.subtract(taxFee).subtract(serviceFee); // 实际提现金额
        AccountCashInfo entity = new AccountCashInfo();
        entity.setSn(AcctIdUtils.getAcctCashSn());
        entity.setCompanyNo(userInfo.getCompanyNo());
        entity.setUserId(userInfo.getId());
        entity.setType(param.getAcctType());
        entity.setAcctId(accountInfo.getId());
        entity.setBankCardId(param.getBankCardId());
        entity.setFund(fund);
        entity.setFundReal(fundReal);
        entity.setTaxFee(taxFee);
        entity.setServiceFee(serviceFee);
        entity.setState(AcctCashConfig.AccountState.APPLY.getCode());
        entity.addCreateParam(userInfo);
        entity.addEditParam(userInfo);
        accountCashInfoService.save(entity);

        //账户冻结

    }

    @Override
    public void applyInfo(AcctCashApplyInfoParam param, LoginSimpleUserInfo userInfo) {
        // 账户验证
        AccountInfo accountInfo = accountInfoService.getOne(new QueryWrapper<AccountInfo>()
                .eq("user_id", userInfo.getId())
                .eq("type", param.getAcctType())
        );
        if (accountInfo == null) {
            throw new BusinessException(AcctErrorEnum.NOT_ACCOUNT);
        }
        if (!accountInfo.getUserId().equals(userInfo.getId())) {
            throw new BusinessException(AcctErrorEnum.NOT_OWNER);
        }
        if (!AcctStateEnum.NORMAL.getCode().equals(accountInfo.getState())) {
            throw new BusinessException(AcctErrorEnum.Acct_state_error);
        }
        if (param.getFund().compareTo(accountInfo.getFund()) > 0) {
            throw new BusinessException(AcctErrorEnum.Acct_Insufficient);
        }
        BigDecimal fund = param.getFund();                      // 提现金额
        BigDecimal balance = new BigDecimal("0.00");        // 税费
        AccountCashInfo entity = new AccountCashInfo();
        entity.setSn(AcctIdUtils.getAcctCashSn());
        entity.setCompanyNo(userInfo.getCompanyNo());
        entity.setUserId(userInfo.getId());
        entity.setType(param.getAcctType());
        entity.setAcctId(accountInfo.getId());
        entity.setBankCardId(0);
        entity.setFund(fund);
        entity.setFundReal(fund);
        entity.setTaxFee(balance);
        entity.setServiceFee(balance);
        entity.setState(AcctCashConfig.AccountState.APPLY.getCode());
        entity.addCreateParam(userInfo);
        entity.addEditParam(userInfo);
        accountCashInfoService.save(entity);

        //提现申请后直接扣除金额
        BigDecimal residueFund = accountInfo.getFund().subtract(fund); // 扣除剩余金额
        accountInfo.setFund(residueFund);
        accountInfo.addCreateParam(userInfo);
        accountInfo.addEditParam(userInfo);
        accountInfo.setId(accountInfo.getId());
        accountInfoService.updateById(accountInfo);
    }


    @Override
    public void applyUpdate(AcctAccountInfoParam param, LoginSimpleUserInfo userInfo) {
        // 账户验证
        AccountInfo accountInfo = accountInfoService.getOne(new QueryWrapper<AccountInfo>()
                .eq("user_id", param.getUserId())
                .eq("type", param.getType())
        );
        if (accountInfo == null) {
            throw new BusinessException(AcctErrorEnum.NOT_ACCOUNT);
        }
        if (!AcctStateEnum.NORMAL.getCode().equals(accountInfo.getState())) {
            throw new BusinessException(AcctErrorEnum.Acct_state_error);
        }
        //查询提现记录数据
        AccountCashInfo accountCashInfo = accountCashInfoService.getOne(new QueryWrapper<AccountCashInfo>()
                .eq("sn", param.getSn())
                .eq("user_id", param.getUserId()));
        if (accountCashInfo == null) {
            throw new BusinessException(AcctErrorEnum.Acct_state_error);
        }
        String state = param.getState();
        switch (state) {
            //提现成功
            case "2":
                //修改提现状态
                accountCashInfo.setState(state);
                accountCashInfoService.updateById(accountCashInfo);
                //修改账户信息操作
                //去除之前提交提现时的金额
                accountInfo.addCreateParam(userInfo);
                accountInfo.addEditParam(userInfo);
                accountInfo.setId(accountInfo.getId());
                accountInfoService.updateById(accountInfo);
                break;
            //提现失败
            case "3":
                //修改提现状态
                accountCashInfo.setState(state);
                accountCashInfoService.updateById(accountCashInfo);

                //修改账户信息操作
                //去除之前提交提现时的金额
                accountInfo.setFund(accountInfo.getFund().add(accountCashInfo.getFund()));
                accountInfo.addCreateParam(userInfo);
                accountInfo.addEditParam(userInfo);
                accountInfo.setId(accountInfo.getId());
                accountInfoService.updateById(accountInfo);
                break;
            default:
                throw new BusinessException("提现状态错误");
        }
    }

    @Override
    public void applyFreeze(AcctAccountInfoParam param, LoginSimpleUserInfo userInfo) {
        // 账户验证
        AccountInfo accountInfo = accountInfoService.getOne(new QueryWrapper<AccountInfo>()
                .eq("user_id", param.getUserId())
                .eq("type", param.getType())
        );
        if (accountInfo == null) {
            throw new BusinessException(AcctErrorEnum.NOT_ACCOUNT);
        }
        if (!AcctStateEnum.NORMAL.getCode().equals(accountInfo.getState())) {
            throw new BusinessException(AcctErrorEnum.Acct_state_error);
        }
        BigDecimal balance = new BigDecimal("0.00");
       // AcctStateEnum acctStateEnum = AcctStateEnum.valueOf(param.getState());

        switch (param.getState()) {
            //冻结
            case "1":
                if (param.getFund()==null) {
                    throw new BusinessException(AcctErrorEnum.Acct_Insufficien);
                }
                if (accountInfo.getFund().compareTo( new BigDecimal(param.getFund() ))== -1 ) {
                    throw new BusinessException(AcctErrorEnum.Acct_Insufficient);
                }

                accountInfo.setFreezeFund(accountInfo.getFreezeFund().add( new BigDecimal(param.getFund())));
                accountInfo.setFund(accountInfo.getFund().subtract( new BigDecimal(param.getFund())));//余额减去冻结数
                accountInfo.addCreateParam(userInfo);
                accountInfo.addEditParam(userInfo);
                accountInfo.setId(accountInfo.getId());
                accountInfoService.updateById(accountInfo);
                break;
            //解冻
            case "2":
                accountInfo.setFund(accountInfo.getFund().add(accountInfo.getFreezeFund()));
                accountInfo.setFreezeFund(balance);
                accountInfo.addCreateParam(userInfo);
                accountInfo.addEditParam(userInfo);
                accountInfo.setId(accountInfo.getId());
                accountInfoService.updateById(accountInfo);
                break;
            default:
                throw new BusinessException("提现状态错误");
        }
    }

    @Override
    public void pointUpdate(AcctAccountInfoParam param, LoginSimpleUserInfo userInfo) {
        // 账户验证
        AccountInfo accountInfo = accountInfoService.getOne(new QueryWrapper<AccountInfo>()
                .eq("user_id", param.getUserId())
                .eq("type", param.getType())
        );
        BigDecimal fund = new BigDecimal(param.getFund());                      // 提现金额
        if (accountInfo == null) {
            BigDecimal balance = new BigDecimal("0.00");        // 税费
            AccountInfo entity = new AccountInfo();
            entity.setCompanyNo("TP");
            entity.setUserId(param.getUserId());
            entity.setType(param.getType());
            entity.setTotalFund(fund);
            entity.setFund(fund);
            entity.setFreezeFund(balance);
            entity.setNotFund(balance);
            entity.setState(AcctCashConfig.AccountState.APPLY.getCode());
            entity.addCreateParam(userInfo);
            entity.addEditParam(userInfo);
            accountInfoService.save(entity);
            //操作账户明细操作
            AcctOpRequestEntiy(entity,userInfo.getCompanyNo(),userInfo, fund);

        }else {
            if (!AcctStateEnum.NORMAL.getCode().equals(accountInfo.getState())) {
                throw new BusinessException(AcctErrorEnum.Acct_state_error);
            }
            accountInfo.setFund(accountInfo.getFund().add(fund));
            accountInfo.setId(accountInfo.getId());
            accountInfo.setTotalFund(accountInfo.getTotalFund().add(fund));
            accountInfo.setId(accountInfo.getId());
            accountInfo.addCreateParam(userInfo);
            accountInfo.addEditParam(userInfo);
            accountInfoService.updateById(accountInfo);
            //操作账户明细操作
            AcctOpRequestEntiy(accountInfo,userInfo.getCompanyNo(),userInfo,fund);
        }



    }
    private void AcctOpRequestEntiy(AccountInfo param, String companyNo, LoginSimpleUserInfo userInfo,BigDecimal fund){
        AccountDetailInfo entity = new AccountDetailInfo();
        entity.setCompanyNo(companyNo);
        entity.setUserId(param.getUserId());
        entity.setType(param.getType());
        entity.setValidityFund(fund);
        entity.setValidityDate(LocalDateTime.now());
        entity.setValidityState(BaseConstant.YNEnum.YES.getCode());
        entity.setConsumeFund(BigDecimal.ZERO);
//        entity.setConsumeDate();
        entity.setOverdueFund(BigDecimal.ZERO);
        entity.setOverdueState(BaseConstant.YNEnum.NO.getCode());
        entity.addCreateParam(userInfo);
        entity.addEditParam(userInfo);
        accountDetailInfoService.saveOrUpdate(entity);
    }

}
